package io.gitee.kotle.android.adapter

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import io.gitee.kotle.android.utils.asOrNull
import io.gitee.kotle.android.utils.onClick
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type

class DefaultRecyclerViewAdapterImpl<Data> : IRecyclerViewAdapter<Data> {

    private val registerHolderMap = mutableMapOf<Type?, RecyclerRegisterInfo?>()

    private var mViewType = RecyclerView.INVALID_TYPE


    /**
     * 设置点击事件
     */
    private val itemClickMap =
        hashMapOf<Int?, ((holder: RecyclerViewHolder<Data, *>, clickView: View) -> Unit)?>()

    /**
     * 长按事件
     */
    private val itemLongClickMap =
        hashMapOf<Int?, ((holder: RecyclerViewHolder<Data, *>, clickView: View) -> Unit)?>()

    /**
     *滚动到最后，用于分页
     */
    private var onScrollEndListener: Function1<Int, Unit>? = null


    override fun onCreateRecyclerViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): RecyclerViewHolder<Data, *> {
        var holder: RecyclerViewHolder<*, *>? = null
        val inflater = LayoutInflater.from(parent.context)
        for ((_, info) in registerHolderMap) {
            if (info?.viewType == viewType) {
                holder = when (info) {
                    is RecyclerRegisterInfo.HolderClass<*, *> -> {
                        info.holderCls.createHolderInstance(
                            inflater,
                            parent,
                            false
                        )
                    }
                    is RecyclerRegisterInfo.HolderDataType<*> -> {
                        info.onCreateHolderListener.invoke(inflater, parent, viewType)
                    }
                    null -> {
                        null
                    }
                }
            }
        }
        val finalHolder = holder.asOrNull<RecyclerViewHolder<Data, *>>()
            ?: throw IllegalArgumentException("不能找到[viewType ${viewType}],对应的MvvmHolder，请检查是否注册对应的MvvmHolder")
        return initHandleEvent(finalHolder, parent)
    }

    override fun onBindRecyclerViewHolder(
        holder: RecyclerViewHolder<Data, *>,
        position: Int,
        payloads: MutableList<Any>,
        isScrollEnd: Boolean,
        item: Data?
    ) {
        if (onScrollEndListener != null && isScrollEnd) {
            onScrollEndListener?.invoke(position)
        }
        if (item != null) {
            holder.onBindData(position, item, payloads)
        }
    }


    override fun getRecyclerViewItemViewType(position: Int, data: Data?): Int {
        val item = data ?: return RecyclerView.INVALID_TYPE
        val dataType = item::class.java
        val info = registerHolderMap[dataType]
            ?: throw IllegalArgumentException(
                "不能找到数据[\n位置：${position}\n类型：${dataType}\n 值：${item}\n]" +
                        ",对应的viewType，请检查是否注册对应的RecyclerViewHolder"
            )
        return info.viewType
    }

    override fun onRecyclerViewHolderAttachedToWindow(holder: RecyclerViewHolder<Data, *>) {
        holder.onViewAttachedToWindow()
    }

    override fun onRecyclerViewHolderDetachedFromWindow(holder: RecyclerViewHolder<Data, *>) {
        holder.onViewDetachedFromWindow()
    }

    override fun onRecyclerViewHolderRecycled(holder: RecyclerViewHolder<Data, *>) {
        holder.onViewRecycled()
    }

    override fun onRecyclerViewHolderFailedToRecycleView(holder: RecyclerViewHolder<Data, *>) {
        holder.onFailedToRecycleView()
    }


    override fun <DataType : Data, Holder : RecyclerViewHolder<DataType, *>> register(
        holderClassInfo: RecyclerRegisterInfo.HolderClass<DataType, Holder>
    ): Boolean {
        val type = getDataTypeFromHolder(holderClassInfo.holderCls) ?: return false
        dealViewType(holderClassInfo)
        return registerHolderMap.put(type, holderClassInfo) == holderClassInfo
    }


    override fun <DataType : Data> registerData(dataTypeInfo: RecyclerRegisterInfo.HolderDataType<DataType>): Boolean {
        val type = dataTypeInfo.dataClass
        dealViewType(dataTypeInfo)
        return registerHolderMap.put(type, dataTypeInfo) == dataTypeInfo
    }

    private fun dealViewType(info: RecyclerRegisterInfo) {
        if (info.viewType == RecyclerView.INVALID_TYPE) {
            mViewType--
            info.viewType = mViewType
        }
    }

    override fun <DataType : Data, Holder : RecyclerViewHolder<DataType, *>> unRegister(holderClass: Class<Holder>?) {
        unRegisterData(getDataTypeFromHolder(holderClass)?.asOrNull<Class<DataType>>())
    }

    override fun <DataType : Data> unRegisterData(dataType: Class<DataType>?) {
        registerHolderMap.remove(dataType)
    }


    private fun getRealType(old: Type?): Type {
        if (old == null) {
            throw IllegalArgumentException("holderClass 只能是[MvvmHolder]类型")
        }
        return if (old is ParameterizedType) {
            old.rawType
        } else {
            old
        }
    }

    private fun getDataTypeFromHolder(holderCls: Class<*>?): Type? {
        holderCls ?: return null
        return getRealType(holderCls.getParameterizedType()?.actualTypeArguments?.get(0))
    }


    /**
     * 是否设置点击事件
     * 防止创建过多无用的对象
     */
    private fun initHandleEvent(
        holder: RecyclerViewHolder<Data, *>,
        parent: ViewGroup
    ): RecyclerViewHolder<Data, *> {
        holder.parent = parent
        for ((itemClickId, listener) in itemClickMap) {
            val view: View? = if (itemClickId != null) {
                holder.itemView.findViewById(itemClickId)
            } else {
                holder.itemView
            }
            view?.onClick {
                listener?.invoke(holder, it)
            }
        }
        for ((itemClickId, listener) in itemLongClickMap) {
            val view: View? = if (itemClickId != null) {
                holder.itemView.findViewById(itemClickId)
            } else {
                holder.itemView
            }
            view?.setOnLongClickListener {
                listener?.invoke(holder, it)
                true
            }
        }
        holder.onInitFinished(parent)
        return holder
    }

    override fun setOnHolderClickListener(
        clickId: Int?,
        listener: ((holder: RecyclerViewHolder<Data, *>, clickView: View) -> Unit)
    ) {
        itemClickMap[clickId] = listener
    }

    override fun setOnHolderLongClickListener(
        clickId: Int?,
        listener: ((holder: RecyclerViewHolder<Data, *>, clickView: View) -> Unit)
    ) {
        itemLongClickMap[clickId] = listener
    }

    /**
     * 设置滑到底部的监听
     */
    override fun setOnScrollEndListener(l: Function1<Int, Unit>?) {
        this.onScrollEndListener = l
    }

    override fun getItemData(position: Int): Data? {
        throw IllegalArgumentException("请重写此函数,实现自己逻辑")
    }

}